﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace System.Common
{
  [DebuggerStepThrough]
  [DebuggerNonUserCode]
  [Serializable]
  public class WeakEvent : WeakEventBase
  {
    ~WeakEvent()
    {
      Dispose();
    }

    public void Invoke()
    {
      RemoveInvalidDelegates();
      foreach ( var wd in Eventhandlers.ToArray() )
      {
        var target = wd.Target;

        var handler = Delegate.CreateDelegate( typeof( Action ), target, wd.Method ) as Action;

        if ( handler != null )
          InternalInvoke( wd, handler );
      }
    }

  }

  public class WeakEvent<T> : WeakEvent
  {
    [DebuggerHidden]
    public void Invoke( T arg, bool isDispatcher = false )
    {
      RemoveInvalidDelegates();

      foreach ( var wd in Eventhandlers.ToArray() )
      {
        var target = wd.Target;

        var handler = Delegate.CreateDelegate( typeof( Action<T> ), target, wd.Method ) as Action<T>;

        if ( handler != null )
          InternalInvoke( wd, () => handler( arg ) );

      }
    }

  }

  public class WeakEvent<T1, T2> : WeakEvent
  {
    [DebuggerHidden]
    public void Invoke( T1 arg1, T2 arg2 )
    {
      RemoveInvalidDelegates();

      foreach ( var wd in Eventhandlers.ToArray() )
      {
        var target = wd.Target;

        var handler = Delegate.CreateDelegate( typeof( Action<T1, T2> ), target, wd.Method ) as Action<T1, T2>;

        if ( handler != null )
          InternalInvoke( wd, () => handler( arg1, arg2 ) );

      }
    }
  }

  public class WeakEvent<T1, T2, T3> : WeakEvent
  {
    public void Invoke( T1 arg1, T2 arg2, T3 arg3 )
    {
      RemoveInvalidDelegates();

      foreach ( var wd in Eventhandlers.ToArray() )
      {
        var target = wd.Target;

        var handler = Delegate.CreateDelegate( typeof( Action<T1, T2, T3> ), target, wd.Method ) as Action<T1, T2, T3>;

        if ( handler != null )
          InternalInvoke( wd, () => handler( arg1, arg2, arg3 ) );

      }
    }

  }
}
